package com.lvxingli.generateannotation.factory.commandtype.impl;

import com.intellij.lang.jvm.annotation.JvmAnnotationAttribute;
import com.intellij.lang.jvm.annotation.JvmAnnotationAttributeValue;
import com.intellij.psi.PsiAnnotation;
import com.lvxingli.generateannotation.constants.ModifierAnnotationEnum;
import com.lvxingli.generateannotation.exception.ExceptionMsgEnum;
import com.lvxingli.generateannotation.factory.commandtype.ICommandTypeProcessor;
import com.lvxingli.generateannotation.factory.commandtype.base.AbstractCommandTypeProcessor;
import com.lvxingli.generateannotation.pojo.*;
import com.lvxingli.generateannotation.util.CommentParseUtils;
import com.lvxingli.generateannotation.util.ExceptionUtils;
import com.lvxingli.generateannotation.util.GenerateUtils;
import com.lvxingli.generateannotation.util.ModifierAnnotationUtils;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.lvxingli.generateannotation.util.GenerateUtils.writeAnnotationOriginalPrimary;

/**
 * Swagger注解填充处理器
 *
 * @author lvxingli
 */
public class CommandTypePopulateWriteSwaggerProcessor extends AbstractCommandTypeProcessor implements ICommandTypeProcessor {

    private final WriteContext writeContext;

    public CommandTypePopulateWriteSwaggerProcessor(WriteContext writeContext) {
        this.writeContext = writeContext;
    }

    @Override
    public void doWriteFile() {
        for (PsiClassWrapper psiClassWrapper : writeContext.getClzList()) {

            if (psiClassWrapper.getClassRole() == PsiClassWrapper.ClassRoleEnum.CONTROLLER) {
                generateClassControllerSwaggerAnnotation(writeContext.getPsiFileContext(), psiClassWrapper);
                for (PsiMethodWrapper psiMethodWrapper : psiClassWrapper.getMethodList()) {
                    generateMethodSwaggerAnnotation(writeContext.getPsiFileContext(), psiMethodWrapper);
                }
                continue;
            }

            if (psiClassWrapper.getClassRole() == PsiClassWrapper.ClassRoleEnum.POJO) {
                generateClassPojoSwaggerAnnotation(writeContext.getPsiFileContext(), psiClassWrapper);
                for (PsiFieldWrapper psiFieldWrapper : psiClassWrapper.getFieldList()) {
                    generateFieldSwaggerAnnotation(writeContext.getPsiFileContext(), psiFieldWrapper);
                }
            }
        }
    }

    @Override
    public void doWriteElement() {
        SelectWrapper selectWrapper = writeContext.getSelectWrapper();
        PsiClassWrapper psiClassWrapper = selectWrapper.getSelectedPsiClassWrapper();
        if (!selectWrapper.isSelected()) {
            throw ExceptionUtils.newException(ExceptionMsgEnum.ELEMENT_NOT_SELECT);
        }

        if (selectWrapper.getClz() != null) {
            if (psiClassWrapper.getClassRole() == PsiClassWrapper.ClassRoleEnum.CONTROLLER) {
                generateClassControllerSwaggerAnnotation(writeContext.getPsiFileContext(), psiClassWrapper);
            } else if (psiClassWrapper.getClassRole() == PsiClassWrapper.ClassRoleEnum.POJO) {
                generateClassPojoSwaggerAnnotation(writeContext.getPsiFileContext(), psiClassWrapper);
            }
            return;
        }

        if (selectWrapper.getMethod() != null) {
            generateMethodSwaggerAnnotation(writeContext.getPsiFileContext(), selectWrapper.getMethod());
            return;
        }

        if (selectWrapper.getField() != null) {
            generateFieldSwaggerAnnotation(writeContext.getPsiFileContext(), selectWrapper.getField());
        }
    }

    /**
     * 生成类的Swagger注解
     */
    private static void generateClassPojoSwaggerAnnotation(WriteContext.PsiFileContext psiFileContext, PsiClassWrapper psiClassWrapper) {
        PsiClass psiClass = psiClassWrapper.getPsiClass();
        String commentDesc = CommentParseUtils.beautifyCommentFromJavaDoc(psiClass.getDocComment());
        writeAnnotationOriginalPrimary(psiFileContext, ModifierAnnotationUtils.createWrapperApiModel(commentDesc), psiClass);
    }

    /**
     * 生成类的Swagger注解
     */
    private static void generateClassControllerSwaggerAnnotation(WriteContext.PsiFileContext psiFileContext, PsiClassWrapper psiClassWrapper) {
        PsiClass psiClass = psiClassWrapper.getPsiClass();
        String commentDesc = CommentParseUtils.beautifyCommentFromJavaDoc(psiClass.getDocComment());
        writeAnnotationOriginalPrimary(psiFileContext, ModifierAnnotationUtils.createWrapperApi(commentDesc), psiClass);
    }

    /**
     * 生成属性的Swagger注解
     *
     * @param psiFieldWrapper 类属性元素
     */
    private static void generateFieldSwaggerAnnotation(WriteContext.PsiFileContext psiFileContext, PsiFieldWrapper psiFieldWrapper) {
        PsiField psiField = psiFieldWrapper.getPsiField();

        //排除掉某些字段
        if (CommentParseUtils.isExcludeFiled(psiField)) return;


        //优先级1 如果有FieldAnnotation注解的话，转换FieldAnnotation注解为ApiModelProperty（保留原注解）
        Map<String, String> map = CommentParseUtils.getFieldAnnotationValue(psiField, "cn.com.nyfb.framework.annotation.FieldAnnotation");//拿到FieldAnnotation里面的信息
        if (map != null && map.size() > 0) {
            //删除原注解
            GenerateUtils.deleteAnnotation(ModifierAnnotationEnum.FIELD_ANNOTATION, psiField);
            writeAnnotationOriginalPrimary(psiFileContext, ModifierAnnotationUtils.createWrapperApiModelPropertyByFieldAnnotation(map), psiField);
            return;
        }

        //优先级2 如果有FieldClassAnnotation注解的话，转换FieldClassAnnotation注解为ApiModelProperty（保留原注解）
        Map<String, String> map2 = CommentParseUtils.getFieldAnnotationValue(psiField, "cn.com.nyfb.framework.annotation.FieldClassAnnotation");//拿到FieldClassAnnotation里面的信息
        if (map2 != null && map2.size() > 0) {
            //删除原注解
            GenerateUtils.deleteAnnotation(ModifierAnnotationEnum.FIELD_CLASS_ANNOTATION, psiField);
            writeAnnotationOriginalPrimary(psiFileContext, ModifierAnnotationUtils.createWrapperApiModelPropertyByFieldClassAnnotation(map2), psiField);
            return;
        }
        String commentDesc = null;

        //优先级3 根据 //注解生成注解
        commentDesc = CommentParseUtils.beautifyCommentFromJavaDocLine(psiField);
        if (isNotEmpty(commentDesc)) {
            //删除原注释
            CommentParseUtils.deleteCommentFromJavaDocLine(psiField);
            writeAnnotationOriginalPrimary(psiFileContext, ModifierAnnotationUtils.createWrapperApiModelProperty(commentDesc), psiField);
            return;
        }

        //兜底用多行注释来填充
        commentDesc = CommentParseUtils.beautifyCommentFromJavaDoc(psiField.getDocComment());
        if (isNotEmpty(commentDesc)) {
            psiField.getDocComment().delete();
        } else {
            //如果多行没有取到的话，可能是在字段上一行的单行注释
            commentDesc = CommentParseUtils.beautifyCommentFromJavaDocPreLine(psiField);
            if (isNotEmpty(commentDesc)) {
                CommentParseUtils.deleteCommentFromJavaDocPreLine(psiField);
            }
        }
        if (isEmpty(commentDesc)){
            return;
        }
        writeAnnotationOriginalPrimary(psiFileContext, ModifierAnnotationUtils.createWrapperApiModelProperty(commentDesc), psiField);
    }

    private static boolean isNotEmpty(String str) {
        return StringUtils.isNotBlank(str) && !"null".equalsIgnoreCase(str);
    }

    private static boolean isEmpty(String str) {
        return StringUtils.isBlank(str) || "null".equalsIgnoreCase(str);
    }

    /**
     * 生成方法的Swagger注解
     *
     * @param psiMethodWrapper 类属性元素
     */
    private static void generateMethodSwaggerAnnotation(WriteContext.PsiFileContext psiFileContext, PsiMethodWrapper psiMethodWrapper) {
        PsiMethod psiMethod = psiMethodWrapper.getPsiMethod();
        String commentDesc = CommentParseUtils.beautifyCommentFromJavaDoc(psiMethod.getDocComment());
        writeAnnotationOriginalPrimary(psiFileContext, ModifierAnnotationUtils.createWrapperApiOperation(commentDesc), psiMethod);
    }

}
